﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using VmcRemote.Common;

namespace VmcRemote.WM6.Standard
{
    public partial class RemoteForm : Form
    {
        delegate void StatusChangedDelegate(object sender, ConnectionStatusChangedEventArgs e);
        delegate void ErrorOccurredDelegate(object sender, RemoteErrorEventArgs e);

        private const string FormTitle = "VMC Remote";

        Remote remote;

        public RemoteForm()
        {
            InitializeComponent();
        }

        #region Form Events
        
        private void RemoteForm_Load(object sender, EventArgs e)
        {
            SettingsForm form = new SettingsForm();
            form.ShowDialog();
            RemoteSettings settings = form.Settings;

            if (settings == null)
            {
                this.Close();
            }
            else
            {
                VmcRemote.Common.Interfaces.IConnection connection = form.Settings.CreateConnection();
                // subscribing directly to this event is a hack to display the current connection status of the server.
                connection.ConnectionStatusChanged += new EventHandler<ConnectionStatusChangedEventArgs>(server_ConnectionStatusChanged);
                server_ConnectionStatusChanged(connection, new ConnectionStatusChangedEventArgs { Status = ConnectionStatus.Open });
                VmcRemote.Common.Interfaces.IMediaCenter server = form.Settings.CreateServer();

                remote = new Remote(connection, server);
                // subscribing to this event will let us know when there is an error with the remote issuing the command.
                remote.ErrorOccurred += new EventHandler<RemoteErrorEventArgs>(remote_ErrorOccurred);

                SetupScreenControls();
            }
        }

        private void RemoteForm_Resize(object sender, EventArgs e)
        {
            SetupScreenControls();
        }

        private void exitMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        protected override void OnClosing(CancelEventArgs e)
        {
            if (remote != null) remote.Dispose();
            base.OnClosing(e);
        }
        
        #endregion

        #region Remote Events
        
        void server_ConnectionStatusChanged(object sender, ConnectionStatusChangedEventArgs e)
        {
            //Server server = sender as Server;
            if (this.InvokeRequired)
            {
                this.Invoke(new StatusChangedDelegate(server_ConnectionStatusChanged), sender, e);
                return;
            }

            string status = string.Empty;
            switch (e.Status)
            {
                case ConnectionStatus.Open:
                    connectingPanel.Visible = false;
                    this.Enabled = true;
                    status = " - Connected";
                    break;
                case ConnectionStatus.Closed:
                    connectingPanel.Visible = false;
                    this.Enabled = true;
                    status = " - (Connection Closed)";
                    break;
                case ConnectionStatus.Connecting:
                    connectingPanel.Visible = true;
                    this.Enabled = false;
                    status = " - Connecting...";
                    break;
                default:
                    break;
            }
            this.Text = FormTitle + status;
        }

        void remote_ErrorOccurred(object sender, RemoteErrorEventArgs e)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new ErrorOccurredDelegate(remote_ErrorOccurred), sender, e);
                return;
            }

            MessageBox.Show(
                string.Format(
                    "Could not communicate with server. The following error occurred:\n{0}\n\n" +
                    "If the problem persists, please restart the listening process and try again.",
                    e.Error.Message
                    ),
                "VMC Remote",
                MessageBoxButtons.OK, MessageBoxIcon.Asterisk, MessageBoxDefaultButton.Button1);
        }
        
        #endregion

        #region Key and Menu Item Events

        private void RemoteForm_KeyDown(object sender, KeyEventArgs e)
        {
            RemoteCommand command = MapKeyToCommand(e.KeyCode);
            if (command != (RemoteCommand)0)
                ExecuteCommand(command);
        }

        private void homeMenuButton_Click(object sender, EventArgs e)
        {
            ExecuteCommand(RemoteCommand.Home);
        }

        private void recordedTvMenuButton_Click(object sender, EventArgs e)
        {
            ExecuteCommand(RemoteCommand.RecordedTv);
        }

        private void liveTvMenuButton_Click(object sender, EventArgs e)
        {
            ExecuteCommand(RemoteCommand.LiveTv);
        }

        private void guideMenuButton_Click(object sender, EventArgs e)
        {
            ExecuteCommand(RemoteCommand.Guide);
        }

        private void videosMenuButton_Click(object sender, EventArgs e)
        {
            ExecuteCommand(RemoteCommand.Videos);
        }

        private void picturesMenuButton_Click(object sender, EventArgs e)
        {
            ExecuteCommand(RemoteCommand.Pictures);
        }

        private void musicMenuButton_Click(object sender, EventArgs e)
        {
            ExecuteCommand(RemoteCommand.Music);
        }

        private void startMceMenuButton_Click(object sender, EventArgs e)
        {
            ExecuteCommand(RemoteCommand.StartMediaCenter);
        }

        private void sleepMenuItem_Click(object sender, EventArgs e)
        {
            ExecuteCommand(RemoteCommand.Sleep);
        }

        private void restartMenuItem_Click(object sender, EventArgs e)
        {
            ExecuteCommand(RemoteCommand.Restart);
        }

        private void shutDownMenuItem_Click(object sender, EventArgs e)
        {
            ExecuteCommand(RemoteCommand.ShutDown);
        }

        private void closeMenuItem_Click(object sender, EventArgs e)
        {
            ExecuteCommand(RemoteCommand.CloseMediaCenter);
        }

        private void dvdMenuItem_Click(object sender, EventArgs e)
        {
            ExecuteCommand(RemoteCommand.Dvd);
        }

        #endregion

        private void ExecuteCommand(RemoteCommand command)
        {
            try
            {
                if (!connectingPanel.Visible)
                    remote.ExecuteCommand(command);
            }
            catch { }
        }

        private static RemoteCommand MapKeyToCommand(Keys keyCode)
        {
            RemoteCommand command;
            switch (keyCode)
            {
                case Keys.Up:
                    command = RemoteCommand.MoveUp;
                    break;
                case Keys.Right:
                    command = RemoteCommand.MoveRight;
                    break;
                case Keys.Left:
                    command = RemoteCommand.MoveLeft;
                    break;
                case Keys.Down:
                    command = RemoteCommand.MoveDown;
                    break;
                case Keys.Enter:
                    command = RemoteCommand.Ok;
                    break;
                case Keys.D0:
                    command = RemoteCommand.Record;
                    break;
                case Keys.D1:
                    command = RemoteCommand.SkipBack;
                    break;
                case Keys.D2:
                    command = RemoteCommand.SkipForward;
                    break;
                case Keys.D3:
                    command = RemoteCommand.Stop;
                    break;
                case Keys.D4:
                    command = RemoteCommand.Rewind;
                    break;
                case Keys.D5:
                    command = RemoteCommand.FastForward;
                    break;
                case Keys.D6:
                    command = RemoteCommand.PlayPause;
                    break;
                case Keys.D7:
                    command = RemoteCommand.Back;
                    break;
                case Keys.D8:
                    command = RemoteCommand.ContextMenu;
                    break;
                case Keys.D9:
                    command = RemoteCommand.Play;
                    break;
                case Keys.I:
                    command = RemoteCommand.ChannelUp;
                    break;
                case Keys.K:
                    command = RemoteCommand.ChannelDown;
                    break;
                case Keys.O:
                    command = RemoteCommand.VolumeUp;
                    break;
                case Keys.L:
                    command = RemoteCommand.VolumeDown;
                    break;
                case Keys.P:
                    command = RemoteCommand.Mute;
                    break;
                default:
                    command = (RemoteCommand)0;
                    break;
            }
            return command;
        }

        private void SetupScreenControls()
        {
            if (this.Width < 300)
            {
                dpadPicture.Visible = false;
                specialPictureBox.Visible = false;
            }

            connectingPanel.Top = (this.Height - connectingPanel.Height) / 2;
            connectingPanel.Left = (this.Width - connectingPanel.Width) / 2;
        }
    }
}